package me.gacl.websocket;

import com.alibaba.fastjson.JSON;
import me.gacl.websocket.JSR356.example.PushDataUtil;
import me.gacl.websocket.JSR356.example.SessionUtils;
import me.gacl.websocket.wsmessages.StringWebsocketMessage;

import javax.websocket.Session;
import java.util.*;

/**
 * 数据推送任务
 * Created by 孤傲苍狼 on 2016/2/18.
 */
public class DataPushTask implements Runnable {

    /**
     * 数据推送任务执行时间设置
     */
    public static final int FIRST_RUN_DELAY_SECONDS = 10;// 10秒后开始执行第一次任务
    public static final int PERIOD_SECONDS = 1;// 以后每隔1秒定时执行任务
    //public static final int PERIOD_SECONDS = 10;// 以后每隔10秒定时执行任务
    //记录任务执行次数的计数器
    private static int count;
    //接收推送数据的目标webSocket客户端集合
    private static Map<String, Session> mapAcceptDataWebSocketClient = new HashMap<String, Session>();
    //记录SessionUtils.webSocketClientInfos的数据集合
    private List<WebSocketClientInfo> lstAllWebSocketClientInfos = new ArrayList<WebSocketClientInfo>();
    //用于存储需要新推送的数据,针对那些已经推送过数据的客户端使用
    private List<WebSocketClientInfo> lstNewWebSocketClientInfos = new ArrayList<WebSocketClientInfo>();
    //记录记录接受过推送数据的客户端的Id集合
    private List<String> lstClientIdRecords = new ArrayList<String>();

    public void run() {
        System.out.println("开始执行任务");
        count++;
        List<WebSocketClientInfo> webSocketClientInfos = SessionUtils.webSocketClientInfos;
        //SessionUtils.clients保存了所有连接上来的WebSocket客户端
        Map<String, Session> clients = SessionUtils.clients;
        //从clients集合中找出需要接收推送数据的webSocket目标客户端
        for (Map.Entry<String, Session> entry : clients.entrySet()) {
            String clientId = entry.getKey();
            Session webSocketClientSession = entry.getValue();
            String clientName = clientId.split("\\_")[0];
            if (clientName.equals("webSocketClientList")) {
                if (!mapAcceptDataWebSocketClient.containsKey(clientId)) {
                    //将需要接受推送数据的WebSocketClient对应的Session添加到map中
                    mapAcceptDataWebSocketClient.put(clientId, webSocketClientSession);
                }
            }
        }

        if (mapAcceptDataWebSocketClient.size() > 0) {
            //将每次需要推送webSocketClientInfos集合中的数据添加到lstAllWebSocketClientInfos进行备份保存
            lstNewWebSocketClientInfos.clear();//每一次执行推送任务之前都先清空lstNewWebSocketClientInfos集合中的元素
            for(WebSocketClientInfo webSocketClientInfo:webSocketClientInfos){
                /**
                 * 判断lstAllWebSocketClientInfos集合中是否包含有WebSocketClientInfo对象,
                 * WebSocketClientInfo类需要重写equals方法,自定义两个webSocketClientInfo对象是否相等的判断方式
                 */
                if (!lstAllWebSocketClientInfos.contains(webSocketClientInfo)){
                    lstAllWebSocketClientInfos.add(webSocketClientInfo);
                    //添加需要给已经推送过数据的客户端推送的新数据集合到lstNewWebSocketClientInfos
                    lstNewWebSocketClientInfos.add(webSocketClientInfo);
                }
            }
            //循环推送数据到客户端
            for (Map.Entry<String, Session> entry : mapAcceptDataWebSocketClient.entrySet()) {
                String clientId = entry.getKey();
                //这个客户端是新连接上来的,还没有推送过数据,推送lstAllWebSocketClientInfos集合中的全部数据到新的客户端
                if (!lstClientIdRecords.contains(clientId)) {
                    System.out.println(clientId+"这个客户端是新连接上来的,还没有推送过数据,开始执行数据推送,推送的内容是webSocketClientInfos集合中的数据");
                    StringWebsocketMessage message = new StringWebsocketMessage();
                    //message.setMessage(lstAllWebSocketClientInfos);
                    /**
                     * webSocketClientInfos集合代表了当前连接上来的WebSocket客户端集合信息,
                     * webSocketClientInfos集合数据由于要进行增加和删除操作,因此是实时变化的
                     * webSocketClientInfos集合数据由于要进行删除操作,因此与lstAllWebSocketClientInfos集合的备份数据是不相等的.
                     * 所以推送全部客户端连接数据要以webSocketClientInfos集合数据为准
                     */
                    message.setMessage(webSocketClientInfos);
                    message.setMessageType(Const.StringWebsocketMessageType.DATA_MESSAGE);
                    //将需要推送的数据转成JSON字符串
                    String messageData = JSON.toJSONString(message);
                    //推送全部数据到新连接的客户端
                    PushDataUtil.pushData(clientId, messageData);
                    lstClientIdRecords.add(clientId);//记录接受过推送数据的客户端的Id
                } else {
                    /**
                     * 客户端之前已经接受过数据推送了,推送新的数据到客户端
                     */
                    if (lstNewWebSocketClientInfos.size() > 0) {
                        System.out.println(clientId+"客户端之前已经接受过数据推送了,开始执行数据推送,推送的内容是lstNewWebSocketClientInfos集合中的数据");
                        StringWebsocketMessage message = new StringWebsocketMessage();
                        message.setMessage(lstNewWebSocketClientInfos);
                        message.setMessageType(Const.StringWebsocketMessageType.DATA_MESSAGE);
                        //将需要推送的数据转成JSON字符串
                        String messageData = JSON.toJSONString(message);
                        //推送新数据到指定的客户端
                        PushDataUtil.pushData(clientId, messageData);
                    } else {
                        System.out.println("lstNewWebSocketClientInfos集合为空，没有新的WebSocket客户端连接,不执行数据推送");
                    }
                }
            }
        } else {
            System.out.println("接收推送数据的目标客户端还没有连接，不执行数据推送");
        }

        System.out.println("任务执行了：" + count + "次");
    }
}
